#include "Sort.h"
#include <iomanip>
using namespace std;

/******************************************************************************
 *
 * Définition de la classe Sort
 *
 *****************************************************************************/

/** Constructeur par défaut.
 * Les écoles sont numérotées de 1 à 21. Un sort inexistant est
 * construit en appelant le constructeur par défaut. Le sort "nul"
 * sert de valeur de retour quand on veut accéder à un sort qui
 * n'existe pas (dépassement d'index par exemple).
 *
 * @param ecole numéro de l'école de magie (défaut = 0).
 * @param niveau niveau du sort (défaut = 0).
 * @param numero numéro du sort (défaut = 0).
 */
Sort::Sort(const unsigned int& ecole, const unsigned int& niveau,
	   const unsigned int& numero)
{
  Ecole  = ecole;
  Niveau = niveau;
  Numero = numero;
}

/** Constructeur de copie.
 * Effectue une copie propre d'un sort dans un autre. Normalement ceci
 * ne devrait pas causer de problèmes, mais comme il existe plusieurs
 * fonctions qui retournent un Sort...
 *
 * @param m_sort sort à copier
 */
Sort::Sort(const Sort& m_sort)
{
  Ecole  = m_sort.Ecole;
  Niveau = m_sort.Niveau;
  Numero = m_sort.Numero;  
}

/**
 * Destructeur, ne fait rien de spécial.
 */
Sort::~Sort()
{}

/** Opérateur de comparaison "plus petit", nécessaire pour le tri.
 * La comparaison est effectuée de la manière suivante :\n
 * 1) on compare les écoles.
 * 2) si les écoles sont les mêmes, on compare les niveaux.\n
 * 3) si les écoles et les niveaux sont les mêmes, on compare les numéros.
 *
 * Cela permet d'obtenir un conteneur où les sorts sont groupés par
 * écoles, puis par niveau et apparaissent par ordre alphabétique.
 *
 * @param m_sort sort à comparer
 * @return valeur du test
 */
bool Sort::operator<(const Sort& m_sort) const
{
  if (Ecole < m_sort.Ecole)
    return true;
  else if (Ecole == m_sort.Ecole && Niveau < m_sort.Niveau)
    return true;
  else if (Ecole == m_sort.Ecole && Niveau == m_sort.Niveau && Numero < m_sort.Numero)
    return true;
  else
    return false;
}

/** Opérateurs de comparaison "plus grand", nécessaire pour le tri.
 * La comparaison est effectuée de la manière suivante :\n
 * 1) on compare les écoles.
 * 2) si les écoles sont les mêmes, on compare les niveaux.\n
 * 3) si les écoles et les niveaux sont les mêmes, on compare les numéros.
 *
 * Cela permet d'obtenir un conteneur où les sorts sont groupés par
 * écoles, puis par niveau et apparaissent par ordre alphabétique.
 *
 * @param m_sort sort à comparer
 * @return valeur du test
 */
bool Sort::operator>(const Sort& m_sort) const
{
  if (Ecole > m_sort.Ecole)
    return true;
  else if (Ecole == m_sort.Ecole && Niveau > m_sort.Niveau)
    return true;
  else if (Ecole == m_sort.Ecole && Niveau == m_sort.Niveau && Numero > m_sort.Numero)
    return true;
  else
    return false;
}

/** Opérateurs d'égalité, nécessaire pour le tri.
 * Ici c'est facile : deux sorts sont égaux si et seulement si tous
 * leurs champs sont rigoureusement identiques.
 *
 * @param m_sort sort à comparer
 * @return valeur du test
 */
bool Sort::operator==(const Sort& m_sort) const
{
  return ( (Ecole == m_sort.Ecole) &&
	   (Niveau == m_sort.Niveau) &&
	   (Numero == m_sort.Numero) );
}

/**
 * Retourne le numéro de l'école, qui n'est pas accessible de
 * l'extérieur.
 *
 * @return Ecole
 */
unsigned int Sort::getEcole() const
{
  return Ecole;
}

/**
 * Retourne le niveau du sort, qui n'est pas accessible de
 * l'extérieur.
 *
 * @ return Niveau
 */
unsigned int Sort::getNiveau() const
{
return Niveau;
}

/**
 * Retourne le numéro du sort, qui n'est pas accessible de
 * l'extérieur.
 *
 * @ return Numero
 */
unsigned int Sort::getNumero() const
{
  return Numero;
}

ostream& operator<<(ostream& out, const Sort& m_sort)
{
  return out << setw(2) << m_sort.Ecole << ' ' << m_sort.Niveau << ' ' << setw(2)
	     << m_sort.Numero << ' ';
}
